(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined'
        ? (module.exports = factory())
        : typeof define === 'function' && define.amd
            ? define(factory)
            : ((global = global || self), (global.tpUtils = factory()));
})(this, function () {
    const isDef = (val) => val !== undefined && val !== null;

    // 通用请求
    function request(api, param, msg = true) {
        return new Promise((resolve, reject) => {
            tpHttp['post'](
                this,
                api,
                {param: JSON.stringify(param || {})},
                (data, code, message) => {
                    const res = {data, code, message};
                    if (code == 0) {
                        resolve(data);
                    } else {
                        reject(res);
                        throw new Error('接口：' + api + ' 错误：' + message);
                    }
                }
            );
        });
    }

    // 调用openApi相关
    function requestApi(apiId, key, p) {
        const url = `action=com.top.unifyindustry.rpcIotApi&api_id=${apiId}`;
        const api = `${url}`;
        let {unitId = '5'} = tpSaaSCore.getUserDetails() || {};
        //todo 发布时删掉
        // unitId = 1;
        if (p) {
            param = {apiId: apiId, key: p};
        } else {
            param = {
                apiId: apiId,
                key: Object.assign(
                    {
                        unit_ids: unitId,
                        unitId: unitId,
                        unit_id: unitId,
                        unitIds: unitId,
                    },
                    key
                ),
            };
        }
        return request(api, param, 'post');
    }

    // 调用openApi相关
    function requestApi2(apiId, key) {
        const url = `action=com.top.unifyindustry.rpcIotApiCode&api_id=${apiId}`;
        const api = `${url}`;
        let {unitId = '5'} = tpSaaSCore.getUserDetails() || {};
        //todo 发布时删掉
        // unitId = 1;
        param = {apiId: apiId, key: key};
        return request(api, param, 'post');
    }

    function parseTime(time, cFormat) {
        if (arguments.length === 0) {
            return null;
        }
        const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}';
        const date = getDateObj(time);
        const formatObj = {
            y: date.getFullYear(),
            m: date.getMonth() + 1,
            d: date.getDate(),
            h: date.getHours(),
            i: date.getMinutes(),
            s: date.getSeconds(),
            a: date.getDay(),
        };
        const timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
            let value = formatObj[key];
            // Note: getDay() returns 0 on Sunday
            if (key === 'a') {
                return ['日', '一', '二', '三', '四', '五', '六'][value];
            }
            if (result.length > 0 && value < 10) {
                value = '0' + value;
            }
            return value || 0;
        });
        return timeStr;
    }

    function getDateObj(time) {
        let date;
        if (typeof time === 'object') {
            date = time;
        } else {
            if (typeof time === 'string') {
                if (/^[0-9]+$/.test(time)) {
                    time = parseInt(time);
                } else {
                    time = time.replace(/\-/g, '/');
                }
            }
            if (typeof time === 'number' && time.toString().length === 10) {
                time = time * 1000;
            }
            date = new Date(time);
        }
        return date;
    }

    /**
     * @desc 函数防抖
     * @param func 函数
     * @param wait 延迟执行毫秒数
     * @param immediate true 表立即执行，false 表非立即执行
     */
    function debounce(func, wait, immediate) {
        let timeout, result;

        const debounced = function () {
            const context = this;
            const args = arguments;

            if (timeout) {
                clearTimeout(timeout);
            }
            if (immediate) {
                // 如果已经执行过，不再执行
                const callNow = !timeout;
                timeout = setTimeout(function () {
                    timeout = null;
                }, wait);
                if (callNow) {
                    result = func.apply(context, args);
                }
            } else {
                timeout = setTimeout(function () {
                    func.apply(context, args);
                }, wait);
            }

            return result;
        };

        debounced.cancel = function () {
            clearTimeout(timeout);
            timeout = null;
        };

        return debounced;
    }

    function deepMerge(target, merged) {
        for (const key in merged) {
            if (target[key] && typeof target[key] === 'object') {
                deepMerge(target[key], merged[key]);

                continue;
            }

            if (typeof merged[key] === 'object') {
                target[key] = deepClone(merged[key], true);

                continue;
            }

            target[key] = merged[key];
        }

        return target;
    }

    function deepClone(object, recursion = false) {
        if (!object) return object;

        const {parse, stringify} = JSON;

        if (!recursion) return parse(stringify(object));

        const clonedObj = object instanceof Array ? [] : {};

        if (object && typeof object === 'object') {
            for (const key in object) {
                if (object.hasOwnProperty(key)) {
                    /* eslint-disable-line */
                    if (object[key] && typeof object[key] === 'object') {
                        clonedObj[key] = deepClone(object[key], true);
                    } else {
                        clonedObj[key] = object[key];
                    }
                }
            }
        }

        return clonedObj;
    }

    // 判断是否为空
    function validatenull(val) {
        if (typeof val === 'boolean') {
            return false;
        }
        if (val instanceof Array) {
            if (val.length === 0) return true;
        } else if (val instanceof Object) {
            if (JSON.stringify(val) === '{}') return true;
        } else {
            if (
                val === 'null' ||
                val == null ||
                val === 'undefined' ||
                val === undefined ||
                val === ''
            )
                return true;
            return false;
        }
        return false;
    }

    // 数字
    function isNumber(value) {
        if (isNaN(value)) {
            return false;
        }
        return typeof +value === 'number';
    }

    function toNumber(value, fractionDigits = 2) {
        return isNumber(value) ? Number(value).toFixed(fractionDigits) - 0 : 0;
    }

    function observerDomResize(dom, callback) {
        const MutationObserver =
            window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

        const observer = new MutationObserver(callback);

        observer.observe(dom, {
            attributes: true,
            attributeFilter: ['style'],
            attributeOldValue: true,
        });

        return observer;
    }

    function formatNumber(number) {
        var arr = (number + '').split('.');
        var int = arr[0].split('');
        var fraction = arr[1] || '';
        var r = '';
        var len = int.length;
        int.reverse().forEach(function (v, i) {
            if (i !== 0 && i % 3 === 0) {
                r = v + ',' + r;
            } else {
                r = v + r;
            }
        });
        return r + (!!fraction ? '.' + fraction : '');
    }

    function pieChartAnimation(chart, data, seriesIndex) {
        if (data.length <= 1) return;
        seriesIndex = seriesIndex || 0;
        let index = 0;
        let timer = null;

        function highlightChange(index) {
            for (let i = 0; i < data.length; i++) {
                if (index === i) {
                    chart.dispatchAction({
                        type: 'highlight',
                        seriesIndex: seriesIndex,
                        dataIndex: i,
                    });
                } else {
                    chart.dispatchAction({
                        type: 'downplay',
                        seriesIndex: seriesIndex,
                        dataIndex: i,
                    });
                }
            }
        }

        function startAnimation() {
            stopAnimation();
            timer = setInterval(() => {
                index++;
                if (index === data.length) {
                    index = 0;
                }
                highlightChange(index);
            }, 2000);
        }

        function stopAnimation() {
            clearInterval(timer);
        }

        highlightChange(0);
        startAnimation();
        chart.on('mouseover', (e) => {
            index = e.dataIndex;
            stopAnimation();
            highlightChange(index);
        });
        chart.on('mouseout', (e) => {
            index = e.dataIndex;
            startAnimation();
            // highlightChange(index);
        });
        chart.stopAnimation = stopAnimation;
    }

    function pieChartAnimation2(chart, option, data, callback) {
        if (data.length <= 1) return;
        let index = 0;
        let timer = null;

        function highlightChange(index) {
            option.series[0].data = data;
            option.plotOptions.pie.events = {
                click(e) {
                    index = e.point.index;
                },
                mouseOver(e) {
                    // index = e.target.index;
                    stopAnimation();
                    // highlightChange(index);
                },
                mouseOut(e) {
                    startAnimation();
                },
            };
            chart.update(option);
            for (let i = 0; i < data.length; i++) {
                const active = index === i;
                const item = data[i];
                data[i].sliced = active;
                data[i].selected = active;
                if (active) {
                    callback && callback(item);
                }
            }
        }

        function startAnimation() {
            stopAnimation();
            timer = setInterval(() => {
                index++;
                if (index === data.length) {
                    index = 0;
                }
                highlightChange(index);
            }, 2000);
        }

        function stopAnimation() {
            clearInterval(timer);
        }

        highlightChange(0);
        startAnimation();
        chart.stopAnimation = stopAnimation;
    }

    function getMatchRegionValue(regionCode) {
        regionCode = (regionCode || '').toString();
        const matchArr = regionCode.match(/0+$/);
        let len = 0;
        let value = '';
        if (matchArr) {
            len = matchArr[0].length;
            len = len % 2 === 0 ? len : len - 1; // 必须为偶数
            len = len > 0 ? len : 0;
        }
        if (len) {
            value = regionCode.slice(0, -len);
        } else {
            value = regionCode;
        }
        return value;
    }

    // 换算方法
    function getResizePx(px, defaultWidth = 1920) {
        const width = document.documentElement.clientWidth;
        return px * (width / defaultWidth);
    }

    function getVerticalResizePx(px, defaultWidth = 1080) {
        const width = document.documentElement.clientHeight;
        return px * (width / defaultWidth);
    }

    function getDataMapping(data, key) {
        return data.reduce((pre, cur) => {
            if (pre[cur[key]]) {
                pre[cur[key]].push(cur);
            } else {
                pre[cur[key]] = [cur];
            }
            return pre;
        }, {});
    }

    function getRandomArbitrary(min, max) {
        return Math.random() * (max - min) + min;
    }

    function getRandomInt(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min)) + min; // 不含最大值，含最小值
    }

    function getRandomIntInclusive(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min; // 含最大值，含最小值
    }

    function getRandomColor(min = 0, max = 255) {
        return `rgb(${getRandomIntInclusive(
            min,
            max
        )}, ${getRandomIntInclusive(min, max)}, ${getRandomIntInclusive(min, max)})`;
    }

    // 获取图形中心坐标
    function calculateCenter(lnglatarr) {
        var total = lnglatarr.length;
        var X = 0;
        var Y = 0;
        var Z = 0;

        lnglatarr
            .map((arr) => ({lng: arr[0], lat: arr[1]}))
            .forEach(function (lnglat) {
                var lng = (lnglat.lng * Math.PI) / 180;
                var lat = (lnglat.lat * Math.PI) / 180;
                var x, y, z;
                x = Math.cos(lat) * Math.cos(lng);
                y = Math.cos(lat) * Math.sin(lng);
                z = Math.sin(lat);
                X += x;
                Y += y;
                Z += z;
            });

        X = X / total;
        Y = Y / total;
        Z = Z / total;

        var Lng = Math.atan2(Y, X);
        var Hyp = Math.sqrt(X * X + Y * Y);
        var Lat = Math.atan2(Z, Hyp);

        // return new AMap.LngLat(Lng * 180 / Math.PI, Lat * 180 / Math.PI);
        return [(Lng * 180) / Math.PI, (Lat * 180) / Math.PI];
    }

    /**
     * 求百分比
     * @param  num 当前数
     * @param  total 总数
     */
    function getPercent(num, total) {
        num = parseFloat(num);
        total = parseFloat(total);
        if (isNaN(num) || isNaN(total)) {
            return 0;
        }
        return total <= 0 ? 0 : Math.round((num / total) * 10000) / 100.0;
    }

    // 可以将数字转换成中文大写的表示，处理到万级别，例如 toChineseNum(12345)，返回 一万二千三百四十五
    function toChineseNum(num) {
        const changeNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']; // changeNum[0] = "零"
        const unit = ['', '十', '百', '千', '万'];
        num = parseInt(num);
        const getWan = (temp) => {
            const strArr = temp.toString().split('').reverse();
            let newNum = '';
            for (let i = 0; i < strArr.length; i++) {
                newNum =
                    (i == 0 && strArr[i] == 0
                        ? ''
                        : i > 0 && strArr[i] == 0 && strArr[i - 1] == 0
                            ? ''
                            : changeNum[strArr[i]] + (strArr[i] == 0 ? unit[0] : unit[i])) + newNum; // eslint-disable-line
            }
            return newNum;
        };
        const overWan = Math.floor(num / 10000);
        let noWan = num % 10000;
        if (noWan.toString().length < 4) noWan = '0' + noWan;
        return overWan ? getWan(overWan) + '万' + getWan(noWan) : getWan(num);
    }

    // 获取风向
    function windDirection(dtn) {
        let direction = '';
        if ((dtn >= 337.6 && dtn <= 360) || (dtn >= 0 && dtn <= 22.5)) {
            direction = '北风';
        } else if (dtn >= 22.6 && dtn <= 67.5) {
            direction = '东北风';
        } else if (dtn >= 67.6 && dtn <= 112.5) {
            direction = '东风';
        } else if (dtn >= 112.6 && dtn <= 157.5) {
            direction = '东南风';
        } else if (dtn >= 157.6 && dtn <= 202.5) {
            direction = '南风';
        } else if (dtn >= 202.6 && dtn <= 247.5) {
            direction = '西南风';
        } else if (dtn >= 247.6 && dtn <= 292.5) {
            direction = '西风';
        } else if (dtn >= 292.6 && dtn <= 337.5) {
            direction = '西北风';
        }
        return direction;
    }

    //换算方法
    function nowSize(val, initWidth = 1920) {
        let nowClientWidth = document.documentElement.clientWidth;
        return val * (nowClientWidth / initWidth);
    }

    const cubic = (value) => Math.pow(value, 3);
    const easeInOutCubic = (value) =>
        value < 0.5 ? cubic(value * 2) / 2 : 1 - cubic((1 - value) * 2) / 2;
    const scrollToTop = (el) => {
        const beginTime = Date.now();
        const beginValue = el.scrollTop;
        const rAF = window.requestAnimationFrame || ((func) => setTimeout(func, 16));
        const frameFunc = () => {
            const progress = (Date.now() - beginTime) / 500;
            if (progress < 1) {
                el.scrollTop = beginValue * (1 - easeInOutCubic(progress));
                rAF(frameFunc);
            } else {
                el.scrollTop = 0;
            }
        };
        rAF(frameFunc);
    };

    function getYearOnYear(preVal, curVal) {
        let yearOnYear = '';
        if (tpUtils.toNumber(curVal, 10) && tpUtils.toNumber(preVal, 10)) {
            yearOnYear = ((curVal - preVal) / Math.abs(preVal)) * 100;
        }
        return tpUtils.toNumber(yearOnYear);
    }

    function getFormatterText(text, number, separator) {
        number = number || 3;
        separator = separator || '\n'; // 或 <br>
        var newParamsName = ''; // 返回文字格式
        var paramsNameNumber = text.length; // 获取显示文字长度
        var rowNumber = Math.ceil(paramsNameNumber / number); // 最多能显示几行
        if (paramsNameNumber > number) {
            // 如果长度大于每行最多显示的字数
            for (var p = 0; p < rowNumber; p++) {
                // 循环次数就是行数
                var tempStr = ''; // 每次截取的字符
                var start = p * number; // 截取的起点
                var end = start + number; // 截取的终点
                if (p == rowNumber - 1) {
                    // 最后一行就不换行了
                    tempStr = text.substring(start);
                } else {
                    tempStr = text.substring(start, end) + separator;
                }
                newParamsName += tempStr; // 拼接字符串
            }
        } else {
            newParamsName = text; // 如果小于每行最多显示的字数就返回原来的字符串
        }
        return newParamsName;
    }

    /**
     * 页面显示的设备名称
     */
    function deviceName(device) {
        return device.deviceAlias || device.deviceName || device.device_alias || device.device_name;
    }

    /**
     * 设备图标
     * @param device
     */
    function deviceIcon(device) {
        let sensorTypeId = device.sensorTypeId || device.sensor_type_id;
        if (sensorTypeId != undefined) {
            return 'tp-icon-sensor-' + sensorTypeId;
        } else {
            let deviceTypeId = device.deviceTypeId || device.device_type_id;
            // return DEVICE_ICON[deviceTypeId + ""] || DEVICE_ICON["2"];
        }
    }

    /**
     * 传感器值
     * @param sensor
     * @returns {string}
     */
    function sensorValue(sensor, key) {
        console.log(sensor);
        let {sensor_type_id, precision = 1, sensor_unit = ''} = sensor;
        let value = null;
        if (sensor[key] != undefined && !isNaN(sensor[key])) {
            if (sensor_type_id != 180) {
                value = parseFloat(sensor[key].toFixed(precision));
            } else {
                //风向特殊处理
                return windDirection(sensor[key]);
            }
        } else {
            value = '--';
        }
        return value + sensor_unit;
    }

    /**
     * 构建列表的映射关系
     * @param list
     * @param label
     * @param value
     * @param type
     */
    function buildMap(list = [], type = 'item', label = 'label', value = 'value',) {
        if (list.length) {
            const map = list.reduce((acc, item) => {
                let target = item;
                if (type === 'label') target = item[label]
                acc[item[value]] = target;
                return acc;
            }, {})
            return map;
        }
        return {};
    }

    /**
     * 高德地图边界数据转成区域掩模数据
     * @param boundaries
     * @returns {*[]}
     */
    function getMask(boundaries) {
        let mask = []
        for (var i = 0; i < boundaries.length; i += 1) {
            mask.push([boundaries[i]])
        }
        return mask;
    }

    /**
     * 一堆数组中找出边界顶点坐标
     */
    function getMinMax(coordinates) {
        let points = [];
        const minmax = coordinates.reduce(
            (acc, item) => {
                let {minlat, maxlat, minlng, maxlng} = acc || {};
                const [lng, lat] = item || {};
                points.push(lng);
                points.push(lat);
                if (lat < minlat) {
                    minlat = lat;
                }
                if (lng < minlng) {
                    minlng = lng;
                }
                if (lat > maxlat) {
                    maxlat = lat;
                }
                if (lng > maxlng) {
                    maxlng = lng;
                }
                return {
                    minlat,
                    maxlat,
                    minlng,
                    maxlng,
                };
            },
            {minlat: 100000, minlng: 1000000, maxlat: 0, maxlng: 0}
        );
        return {points, minmax};
    }

    //获取目标天数  如输入 2023-04-14 10 10  输出2023-04-04 2023-04-24
    function getPurpleDate(now, daybefore, dayafter) {
        let date = new Date(now);
        const timestamp1 = date.getTime() - daybefore * 24 * 60 * 60 * 1000;
        const timestamp2 = date.getTime() + dayafter * 24 * 60 * 60 * 1000;

        return [
            new Date(timestamp1).toISOString().substring(0, 10),
            new Date(timestamp2).toISOString().substring(0, 10),
        ];
    }

    //获取当前日期    getDate('-') :2023-05-30      getDate('-',1)：2023年5月30日
    function getDate(spli, type) {
        let date = new Date();
        let y = date.getFullYear();
        let M = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
        let d = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
        if (type) {
            return y + '年' + M + '月' + d + '日';
        } else {
            return y + spli + M + spli + d;
        }
    }

    function getBetweenDateStr(start, end, connector = '/') {
        const startTime = new Date(start);
        const endTime = new Date(end);
        const arr = [];
        while (endTime.getTime() - startTime.getTime() > 0) {
            const year = startTime.getFullYear();
            const month =
                (startTime.getMonth() + 1).toString().length === 1
                    ? '0' + (startTime.getMonth() + 1).toString()
                    : startTime.getMonth() + 1;
            const day =
                startTime.getDate().toString().length === 1
                    ? '0' + startTime.getDate()
                    : startTime.getDate();
            arr.push(year + connector + month + connector + day);
            startTime.setDate(startTime.getDate() + 1);
        }
        return arr;
    }

    //获取目标天数  如输入 2023-04-14 10 10  输出2023-04-04 2023-04-24
    function getPurpleDate(now, daybefore, dayafter) {
        let date = new Date(now);
        const timestamp1 = date.getTime() - daybefore * 24 * 60 * 60 * 1000;
        const timestamp2 = date.getTime() + dayafter * 24 * 60 * 60 * 1000;

        return [
            new Date(timestamp1).toISOString().substring(0, 10),
            new Date(timestamp2).toISOString().substring(0, 10),
        ];
    }

    //获取当前日期    getDate('-') :2023-05-30      getDate('-',1)：2023年5月30日
    function getDate(spli, type) {
        let date = new Date();
        let y = date.getFullYear();
        let M = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
        let d = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
        if (type) {
            return y + '年' + M + '月' + d + '日';
        } else {
            return y + spli + M + spli + d;
        }
    }


    /**
     * 生成唯一标识
     * @returns {string}
     */
    function uuidGenerate(prefix) {
        let d = new Date().getTime();

        if (window.performance && typeof window.performance.now === "function") {
            d += performance.now(); //use high-precision timer if available
        }

        const uuid = 'xxxxxxxx'.replace(/[xy]/g, function (c) {
            const r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d / 16);
            return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
        });

        return prefix + uuid.substring(0, 8);
    }

    /**
     * 转换地块坐标
     * @param pathStr      地块坐标串
     * @param mapLayer     当前地块坐标类型  (1-高德 2-天地图)
     * @param curLayerType 基地图层类型      (1-高德 2-天地图)
     * @returns {*[]}
     */
    function convertStrPolygon2Path(pathStr, mapLayer, curLayerType) {
        let path = [];
        if (pathStr) {
            let lnglatArr = pathStr.split(';');
            for (let i = 0, len = lnglatArr.length; i < len; i++) {
                let lnglatStr = lnglatArr[i];
                if (lnglatStr) {
                    let lnglat = lnglatStr.split(',');
                    let lng = Number(lnglat[0]);
                    let lat = Number(lnglat[1]);

                    // 基地底图是高德，地块底图是天地图，地块坐标gps->高德
                    if (curLayerType == 1 && mapLayer != null && mapLayer == 2) {
                        const wgsLngLat = GPS.gcj_encrypt(lat, lng);
                        lng = wgsLngLat.lon;
                        lat = wgsLngLat.lat;
                    }

                    // 基地底图是天地图，地块底图是高德，地块坐标 高德->gps
                    if (curLayerType == 2 && mapLayer != null && mapLayer == 1) {
                        const wgsLngLat = GPS.gcj_decrypt_exact(lat, lng);
                        lng = wgsLngLat.lon;
                        lat = wgsLngLat.lat;
                    }
                    path.push([lng, lat]);
                }
            }
        }
        return path;
    }

    function objToParams(obj) {
        return Object.keys(obj)
            .map(function (key) {
                return ''.concat(encodeURIComponent(key), '=').concat(encodeURIComponent(obj[key]));
            })
            .join('&');
    }

    /**
     * 节流原理：在一定时间内，只能触发一次
     *
     * @param {Function} func 要执行的回调函数
     * @param {Number} wait 延时的时间
     * @param {Boolean} immediate 是否立即执行
     * @return null
     */
    function throttle(func, wait = 500, immediate = true) {
        let timer, flag;
        return function () {
            const context = this;
            const args = arguments;

            if (immediate) {
                if (!flag) {
                    flag = true
                    // 如果是立即执行，则在wait毫秒内开始时执行
                    typeof func === 'function' && func.apply(context, args)
                    timer = setTimeout(() => {
                        flag = false
                    }, wait)
                }
            } else if (!flag) {
                flag = true
                // 如果是非立即执行，则在wait毫秒内的结束处执行
                timer = setTimeout(() => {
                    flag = false
                    typeof func === 'function' && func.apply(context, args)
                }, wait)
            }
        }
    }

    function getDataModelLabel({items, targetValue, labelKey, valueKey}) {
        labelKey = labelKey || 'label'
        valueKey = valueKey || 'value'
        const [item = {}] = items.filter(t => t[valueKey] == targetValue)
        return item[labelKey] || ''
    }


    return {
        getPurpleDate,
        getDate,
        getBetweenDateStr,
        isDef,
        request,
        requestApi,
        requestApi2,
        convertStrPolygon2Path,
        parseTime,
        deviceName,
        deviceIcon,
        sensorValue,

        debounce,
        throttle,
        deepMerge,
        deepClone,
        validatenull,
        isNumber,
        toNumber,
        formatNumber,
        observerDomResize,
        pieChartAnimation,
        pieChartAnimation2,
        getMatchRegionValue,
        getResizePx,
        getVerticalResizePx,
        getDataMapping,
        getRandomArbitrary,
        getRandomInt,
        getRandomIntInclusive,
        getRandomColor,
        calculateCenter,

        getPercent,
        toChineseNum,
        windDirection,
        nowSize,
        scrollToTop,
        getYearOnYear,
        getFormatterText,
        buildMap,
        getMask,
        getMinMax,

        uuidGenerate,
        objToParams,
        getDataModelLabel,
    };

})
